import { boot } from "quasar/wrappers";
import axios from "axios";
import { parseCookie, selectAccount } from "src/assets/utils";
import { date, extend, Notify } from "quasar";
import { authWindow } from "src/assets/electron";

// Be careful when using SSR for cross-request state pollution
// due to creating a Singleton instance here;
// If any client changes this (global) instance, it might be a
// good idea to move this instance creation inside of the
// "export default () => {}" function below (which runs individually
// for each client)
const api = axios.create({
  baseURL: "https://api.zzzw.top/",
  // baseURL: "http://zbjapi.test/",
});

const zbjAxios = {
  response: {
    use(resolve, reject) {
      this.__resolve = resolve;
      this.__reject = reject;
    },
  },
  async request(url, data, userid, method = "GET", headers) {
    if (!userid && userid !== false) {
      const account = await selectAccount();
      if (account) {
        this.store.commit("common/setCurrentAccount", account);
      }
    }
    /** @type {Electron.ClientRequestConstructorOptions} */
    const options = {
      userid,
      url,
      method,
      partition: `persist:zbj_${userid}`,
      useSessionCookies: true,
    };
    return window.electron
      .clientRequest(options, data, headers)
      .then((res) => {
        return this.response.__resolve ? this.response.__resolve(res) : res;
      })
      .catch((err) => {
        return this.response.__reject ? this.response.__reject(err) : err;
      });
  },
  async post(url, data, cookie, options = {}) {
    const userid = cookie ? parseCookie(cookie).data.userid : null;
    return this.request(url, data, userid, "POST", {
      "Content-Type": "application/json",
    });
  },
  async get(url, data, cookie, options = {}) {
    const userid = cookie ? parseCookie(cookie).data.userid : null;
    return this.request(url, data, userid, "GET", options.headers);
  },
};

export default boot(({ app, store, router }) => {
  zbjAxios.response.use(
    (res) => {
      if (res.redirect.is) {
        const isLogout =
          res.redirect.url.indexOf("https://account.zbj.com/login") >= 0;
        if (isLogout) {
          store.dispatch("persisted/logoutAccount", {
            userid: res.options.userid,
          });
        }
        return Promise.reject(false);
      }
      return Promise.resolve(res.response);
    },
    (err) => {
      return Promise.reject(err);
    }
  );

  api.interceptors.request.use((config) => {
    const token = store.state.persisted.auth.token;
    if (token) {
      config.headers["Authorization"] = token;
    }
    return config;
  });

  api.interceptors.response.use(
    (response) => {
      if (response.headers["authorization"]) {
        store.commit("persisted/setUserinfo", {
          token: response.headers["authorization"],
        });
      }
      const { code, msg, data } = response.data;
      if (code === 0) {
        return Promise.resolve(data);
      }
      switch (code) {
        case 403:
          authWindow.show().then(() => {
            window.close();
          });
          break;
        default:
      }
      if (msg) {
        Notify.create(msg);
      }
      return Promise.reject(response.data);
    },
    (error) => {
      return Promise.reject(error);
    }
  );

  app.config.globalProperties.$axios = axios;
  // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
  //       so you won't necessarily have to import axios in each vue file

  app.config.globalProperties.$api = api;
  // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
  //       so you can easily perform requests against your app's API
});

export { api, zbjAxios };
